home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / plan / src / weekcalc.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  269 lines

  1. /*
  2.  * Arrange entries in the week view.
  3.  *
  4.  *    build_week()            Build the week node trees for all days
  5.  *                    of the week beginning on curr_week.
  6.  *    destroy_week()            Release the week node trees.
  7.  */
  8.  
  9. #include <time.h>
  10. #include <Xm/Xm.h>
  11. #include "cal.h"
  12.  
  13. #define NDAYS        7        /* # of days in a week view */
  14.  
  15.  
  16. extern struct tm *time_to_tm();
  17. extern BOOL lookup_entry(), lookup_next_entry();
  18. extern char *mknotestring();
  19.  
  20. extern struct config    config;        /* global configuration data */
  21. extern struct list    *mainlist;    /* list of all schedule entries */
  22. extern struct user    *user;        /* user list (from file_r.c) */
  23. extern int        nusers;        /* number of users in user list */
  24. extern XFontStruct    *font[NFONTS];    /* fonts: FONT_* */
  25. extern int        curr_year;    /* year being displayed, since 1900 */
  26.  
  27. time_t            curr_week;    /* week being displayed, time in sec */
  28. struct week        week;        /* info on week view */
  29.  
  30.  
  31. /*
  32.  * given the first day of a week, build the data structures that describe
  33.  * all entries in the display. Before calling this routine, set week_curr
  34.  * to 0:00 of the first day of the week.
  35.  */
  36.  
  37. static BOOL add_week_entry();
  38.  
  39. build_week()
  40. {
  41.     struct config    *c = &config;
  42.     time_t        date;        /* midnight of calculated day */
  43.     int        wday;        /* day counter, 0..NDAYS-1 */
  44.     int        nlines=0;    /* total number of bar lines */
  45.     struct tm    *tm;        /* check if wday in same year*/
  46.     struct list    *list;        /* current list: mainlist or user's */
  47.     int        u;        /* user counter, -1 == ourselves */
  48.     struct entry    *ep;        /* ptr to entry in mainlist */
  49.     BOOL        found;        /* TRUE if lookup succeeded */
  50.     struct lookup    lookup;        /* result of entry lookup */
  51.     struct weeknode    *wp;        /* for counting # of lines on a day */
  52.  
  53.     if (!c->week_maxhour) c->week_maxhour = 20;
  54.  
  55.     destroy_week();
  56.     update_user_lists();
  57.     curr_week = date = curr_week - curr_week % 86400;
  58.     for (wday=0; wday < NDAYS; wday++, date+=86400) {
  59.         week.nlines[wday] = 0;
  60.         tm = time_to_tm(date);
  61.         if (tm->tm_year != curr_year)
  62.             continue;
  63.         for (u= -1; u < nusers; u++) {
  64.             if (u != -1 && (user[u].suspended || !user[u].list))
  65.                 continue;
  66.             list = u == -1 ? mainlist : user[u].list,
  67.             found = lookup_entry(&lookup, list, date, TRUE, FALSE);
  68.             for (; found; found = lookup_next_entry(&lookup)) {
  69.                 if (lookup.trigger >= date + 86400)
  70.                     break;
  71.                 ep = &list->entry[lookup.index];
  72.                 if (ep->note && *ep->note == '-')
  73.                     continue;
  74.                 if (!add_week_entry(wday, lookup.trigger,
  75.                         &list->entry[lookup.index],
  76.                         u == -1 ? 0 : &user[u])) {
  77.                     destroy_week();
  78.                     return;
  79.                 }
  80.             }
  81.         }
  82.         for (wp=week.tree[wday]; wp; wp=wp->down)
  83.             week.nlines[wday]++;
  84.         if (!week.nlines[wday])
  85.             week.nlines[wday] = 1;
  86.         nlines += week.nlines[wday];
  87.     }
  88.     week.canvas_xs    = c->week_margin
  89.             + c->week_daywidth
  90.             + c->week_gap
  91.             + c->week_hourwidth *
  92.                     (c->week_maxhour - c->week_minhour)
  93.             + c->week_margin;
  94.  
  95.     week.canvas_ys    = c->week_margin
  96.             + c->week_title
  97.             + c->week_margin
  98.             + c->week_hour
  99.             + NDAYS * c->week_gap
  100.             + nlines * (c->week_barheight + 2*c->week_bargap)
  101.             + c->week_gap
  102.             + c->week_margin;
  103. }
  104.  
  105.  
  106. /*
  107.  * insert an entry into the tree for week day <wday>. Try to find a hole
  108.  * in an existing line, or append a new line if no hole can be found. This
  109.  * routine is used by build_week() only.
  110.  */
  111.  
  112. #define GET_EXTENT(node, ep, begin, end)                   \
  113. {                                       \
  114.     begin = !config.weekwarn ? node->trigger               \
  115.                  : ep->early_warn > ep->late_warn       \
  116.                      ? node->trigger - ep->early_warn  \
  117.                      : node->trigger - ep->late_warn;  \
  118.     end = ep->notime ? node->trigger + config.week_minhour * 3600       \
  119.              : node->trigger + ep->length;               \
  120.     if (!node->textinside)                           \
  121.         end += (node->textlen+6) * 3600/config.week_hourwidth;       \
  122. }
  123.  
  124. static BOOL add_week_entry(wday, time, new, userp)
  125.     int        wday;            /* day counter, 0..NDAYS-1 */
  126.     time_t        time;            /* appropriate trigger time */
  127.     struct entry    *new;            /* entry to insert */
  128.     struct user    *userp;            /* which user owns entry? */
  129. {
  130.     struct weeknode    *node;            /* new week struct */
  131.     struct weeknode    *vert;            /* for finding free line */
  132.     struct weeknode    *horz;            /* for finding free slot */
  133.     struct entry    *old;            /* already inserted entry */
  134.     time_t        new_begin, new_end;    /* extent of entry to insert */
  135.     time_t        old_begin, old_end;    /* extent of existing entry */
  136. #ifdef JAPAN
  137.     int        i, clen = 0, plen = 0;
  138.     strpack        partialstr[MAXPARTIALSTRING];
  139.     unsigned char    strpool[MAXPARTIALCHAR];
  140. #endif
  141.  
  142.     if (!(node = (struct weeknode *)malloc(sizeof(struct weeknode))))
  143.         return(FALSE);
  144.     node->next    = node->prev = node->up = node->down = 0;
  145.     node->entry   = new;
  146.     node->user    = userp;
  147.     node->trigger = time;
  148.     node->text[0] = 0;
  149.     if (config.weekuser && userp && userp->name)
  150.         sprintf(node->text, "(%.20s) ", userp->name);
  151.     strncat(node->text, mknotestring(new),
  152.                 sizeof(node->text)-1-strlen(node->text));
  153.     node->text[sizeof(node->text)-1] = 0;
  154. #ifdef JAPAN
  155.     partialstr->strptr = strpool;
  156.     if ((node->textlen = mixedstrlen_in_pixels(node->text, partialstr,
  157.                            FONT_WNOTE, FONT_JNOTE)) >
  158.             config.week_maxnote) {
  159.         for (i=0; partialstr[i].strptr != NULL &&
  160.               i < MAXPARTIALSTRING ||
  161.                     ((node->textlen = plen), 0); i++) {
  162.             if (plen + partialstr[i].pixlen > config.week_maxnote){
  163.                                 /* Truncating*/
  164.                 partialstr[i].length *=
  165.                     (double)(config.week_maxnote-plen) /
  166.                         (double)partialstr[i].pixlen;
  167.                 node->textlen = config.week_maxnote;
  168.                 if (partialstr[i].length == 0 ||
  169.                     partialstr[i].asciistr == False &&
  170.                    (partialstr[i].length &= ~1) == 0)
  171.                     partialstr[i].strptr = NULL;
  172.                 node->text[clen += partialstr[i].length] ='\0';
  173.                 break;
  174.             } else {
  175.                 clen += partialstr[i].length;
  176.                 plen += partialstr[i].pixlen;
  177.             }
  178.         }
  179.     }
  180. #else
  181.     truncate_string(node->text, config.week_maxnote, FONT_WNOTE);
  182.     node->textlen = strlen_in_pixels(node->text, FONT_WNOTE);
  183. #endif
  184.     node->textinside = new->length * config.week_hourwidth / 3600 -
  185.                     config.week_barheight > node->textlen;
  186.     if (!week.tree[wday]) {
  187.         week.tree[wday] = node;
  188.         return(TRUE);
  189.     }
  190.  
  191.     GET_EXTENT(node, new, new_begin, new_end);
  192.  
  193.     for (vert=week.tree[wday]; vert; vert=vert->down) {
  194.         old = vert->entry;
  195.         GET_EXTENT(vert, old, old_begin, old_end);
  196.         if (new_end <= old_begin) {        /* first in line? */
  197.             node->up   = vert->up;
  198.             node->down = vert->down;
  199.             node->next = vert;
  200.             vert->prev = node;
  201.             return(TRUE);
  202.         }
  203.         for (horz=vert; horz; horz=horz->next) {
  204.             if (new_begin < old_end)
  205.                 break;
  206.             if (!horz->next) {        /* last in line? */
  207.                 node->prev = horz;
  208.                 horz->next = node;
  209.                 return(TRUE);
  210.             }
  211.             old = horz->next->entry;
  212.             GET_EXTENT(horz->next, old, old_begin, old_end);
  213.             if (new_end <= old_begin) {    /* fits in hole? */
  214.                 node->next = horz->next;
  215.                 node->prev = horz;
  216.                 horz->next->prev = node;
  217.                 horz->next = node;
  218.                 return(TRUE);
  219.             }
  220.         }
  221.         if (!vert->down) {            /* append new line? */
  222.             vert->down = node;
  223.             node->up   = vert;
  224.             return(TRUE);
  225.         }
  226.     }
  227.     return(FALSE);    /* we never get here */
  228. }
  229.  
  230.  
  231. /*
  232.  * destroy the week trees for all days.
  233.  */
  234.  
  235. destroy_week()
  236. {
  237.     int        wday;            /* day counter */
  238.     struct weeknode    *vert, *nextvert;    /* line pointer */
  239.     struct weeknode    *horz, *nexthorz;    /* node pointer */
  240.  
  241.     for (wday=0; wday < NDAYS; wday++) {
  242.         for (vert=week.tree[wday]; vert; vert=nextvert) {
  243.             nextvert = vert->down;
  244.             for (horz=vert; horz; horz=nexthorz) {
  245.                 nexthorz = horz->next;
  246.                 free((void *)horz);
  247.             }
  248.         }
  249.         week.tree[wday] = 0;
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255.  * return the length of <string> in pixels.
  256.  */
  257.  
  258. strlen_in_pixels(string, sfont)
  259.     register unsigned char *string;    /* string to truncate */
  260.     int        sfont;        /* FONT_* */
  261. {
  262.     register int    len;        /* length in pixels */
  263.  
  264.     for (len=0; *string; string++)
  265.         len += font[sfont]->per_char
  266.                [*string - font[sfont]->min_char_or_byte2].width;
  267.     return(len);
  268. }
  269.